package com.aim.common.util;

import com.aim.common.constant.Constchar;
import org.apache.ibatis.reflection.ArrayUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @AUTO 数据类型转换工具类
 * @FILE ConverterUtils.java
 * @DATE 2017-8-4 下午5:21:52
 * @Author AIM
 */
public class ConverterUtils {

	private static Logger logger = LoggerFactory.getLogger(ConverterUtils.class);

	private static final int ASCII_LENGTH = 128;
	private static final String[] CACHE = new String[ASCII_LENGTH];

	static {
		for (char c = 0; c < ASCII_LENGTH; c++) {
			CACHE[c] = String.valueOf(c);
		}
	}

	/**
	 * 字符转为字符串<br>
	 * 如果为ASCII字符，使用缓存
	 *
	 * @param c 字符
	 * @return 字符串
	 */
	public static String toString(char c) {
		return c < ASCII_LENGTH ? CACHE[c] : String.valueOf(c);
	}

	/**
	 * <将obj转换为string，如果obj为null则返回defaultVal>
	 *
	 * @param obj        需要转换为string的对象
	 * @param defaultVal 默认值
	 */
	public static String toString(Object obj, String defaultVal) {
		return (obj != null) ? obj.toString().trim() : defaultVal;
	}

	/**
	 * <将obj转换为string，默认为空>
	 *
	 * @param obj 需要转换为string的对象
	 */
	public static String toString(Object obj) {
		return toString(obj, "");
	}

	/**
	 * <将对象转换为int>
	 *
	 * @param obj        需要转换为int的对象
	 * @param defaultVal 默认值
	 */
	public static Integer toInt(Object obj, Integer defaultVal) {
		try {
			return (obj != null) ? Integer.parseInt(toString(obj, "0")) : defaultVal;
		} catch (Exception e) {
			return defaultVal;
		}
	}

	/**
	 * <将对象转换为int>
	 *
	 * @param obj 需要转换为int的对象
	 */
	public static Integer toInt(Object obj) {
		return toInt(obj, 0);
	}

	/**
	 * <将对象转换为Integer>
	 *
	 * @param obj 需要转换为Integer的对象
	 * @return obj转换成的Integer值
	 */
	public static Integer toInteger(Object obj) {
		return toInt(obj, null);
	}

	/**
	 * <将对象转换为int>
	 *
	 * @param obj        需要转换为int的对象
	 * @param defaultVal 默认值
	 */
	public static Float toFloat(Object obj, float defaultVal) {
		return (obj != null) ? Float.parseFloat(toString(obj, "0")) : defaultVal;
	}

	/**
	 * <将对象转换为Float>
	 *
	 * @param obj 需要转换为Float的对象
	 */
	public static Float toFloat(Object obj) {
		return toFloat(obj, 0);
	}

	/**
	 * <将obj转换为long>
	 *
	 * @param obj        需要转换的对象
	 * @param defaultVal 默认值
	 */
	public static Long toLong(Object obj, long defaultVal) {
		return (obj != null) ? Long.parseLong(toString(obj)) : defaultVal;
	}

	/**
	 * <将obj转换为long>
	 *
	 * @param obj 需要转换的对象
	 */
	public static Long toLong(Object obj) {
		return toLong(obj, 0l);
	}

	/**
	 * 将object转换为double类型，如果出错则返回 defaultVal
	 *
	 * @param obj        需要转换的对象
	 * @param defaultVal 默认值
	 */
	public static Double toDouble(Object obj, Double defaultVal) {
		try {
			return Double.parseDouble(obj.toString());
		} catch (Exception e) {
			return defaultVal;
		}
	}

	/**
	 * 将object转换为double类型，如果出错则返回 0d
	 *
	 * @param obj 需要转换的对象
	 */
	public static double toDouble(Object obj) {
		return toDouble(obj, 0d);
	}

	public static Map<String, Object> Obj2Map(Object obj) throws Exception {
		Map<String, Object> map = new HashMap<String, Object>();
		Field[] fields = obj.getClass().getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);
			map.put(field.getName(), field.get(obj));
		}
		return map;
	}

	/**
	 * 将对象转为字符串<br>
	 * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
	 *
	 * @param obj 对象
	 * @return 字符串
	 */
	public static String utf8Str(Object obj) {
		return str(obj, Constchar.CHARSET_UTF_8);
	}

	/**
	 * 将对象转为字符串<br>
	 * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
	 *
	 * @param obj     对象
	 * @param charset 字符集
	 * @return 字符串
	 */
	public static String str(Object obj, Charset charset) {
		if (null == obj) {
			return null;
		}

		if (obj instanceof String) {
			return (String) obj;
		} else if (obj instanceof byte[] || obj instanceof Byte[]) {
			return new String((byte[]) obj, OftenUtil.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset.name()));
		} else if (obj instanceof ByteBuffer) {
			return charset.decode((ByteBuffer) obj).toString();
		} else if (obj.getClass().isArray()) {
			return ArrayUtil.toString(obj);
		}

		return obj.toString();
	}

	/**
	 * <将List<Object>转换为List<Map<String, Object>>>
	 *
	 * @param list 需要转换的list
	 */
	public static List<Map<String, Object>> converterForMapList(List<Object> list) throws Exception {
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		for (Object tempObj : list) {
			result.add(Obj2Map(tempObj));
		}
		return result;
	}

	/**
	 * 将 JavaBean对象转化为 Map
	 *
	 * @param bean 要转化的类型
	 * @return Map对象
	 */
	public static Map<String, Object> convertBean2Map(Object bean) {
		if (bean == null) {
			return null;
		}
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
			for (PropertyDescriptor property : propertyDescriptors) {
				String key = property.getName();
				// 过滤class属性
				if (!key.equals("class")) {
					// 得到property对应的getter方法
					Method getter = property.getReadMethod();
					Object value = getter.invoke(bean);
					map.put(key, value);
				}
			}
		} catch (Exception e) {
			throw new RuntimeException("JavaBean对象转化为 Map异常");
		}

		return map;
	}

	/**
	 * Map转Bean
	 */
	public static <T> T converterMap2Bean(Map<?, ?> map, Class<T> clz) {
		T obj = null;
		try {
			obj = clz.newInstance();
			BeanInfo beanInfo = Introspector.getBeanInfo(clz);
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
			for (PropertyDescriptor property : propertyDescriptors) {
				String key = property.getName();
				if (map.containsKey(key)) {
					Object value = map.get(key);
					if (null != value) {
						String v = value.toString();// 值
						// property对应的setter方法
						Method setter = property.getWriteMethod();
						Class<?>[] clazz = setter.getParameterTypes();
						String type = clazz[0].getName();
						if ("java.lang.Byte".equals(type) || "byte".equals(type)) {
							setter.invoke(obj, Byte.parseByte(v));
						} else if ("java.lang.Short".equals(type) || "short".equals(type)) {
							setter.invoke(obj, Short.parseShort(v));
						} else if ("java.lang.Integer".equals(type) || "int".equals(type)) {
							setter.invoke(obj, Integer.parseInt(v));
						} else if ("java.lang.Long".equals(type) || "long".equals(type)) {
							setter.invoke(obj, Long.parseLong(v));
						} else if ("java.lang.Float".equals(type) || "float".equals(type)) {
							setter.invoke(obj, Float.parseFloat(v));
						} else if ("java.lang.Double".equals(type) || "double".equals(type)) {
							setter.invoke(obj, Double.parseDouble(v));
						} else if ("java.lang.String".equals(type)) {
							setter.invoke(obj, v);
						} else if ("java.lang.Character".equals(type) || "char".equals(type)) {
							setter.invoke(obj, (Character) value);
						} else if ("java.util.Date".equals(type)) {
							SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
							setter.invoke(obj, sdf.parse(v));
						} else if ("java.lang.Date".equals(type)) {
							setter.invoke(obj, new Date(((java.sql.Date) value).getTime()));
						} else if ("java.lang.Timer".equals(type)) {
							setter.invoke(obj, new Time(((Time) value).getTime()));
						} else if ("java.sql.Timestamp".equals(type)) {
							setter.invoke(obj, (java.sql.Timestamp) value);
						} else {
							setter.invoke(obj, value);
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("map转{}异常", clz.getName(), e);
		}
		return obj;
	}

	/**
	 * 将 List<JavaBean>对象转化为List<Map>
	 */
	public static List<Map<String, Object>> convertListBean2ListMap(List<?> beanList) {
		List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
		try {
			for (int i = 0, n = beanList.size(); i < n; i++) {
				Object bean = beanList.get(i);
				Map<String, Object> map = convertBean2Map(bean);
				mapList.add(map);
			}
		} catch (Exception e) {
			throw new RuntimeException("List<JavaBean>对象转化为List<Map>异常");
		}
		return mapList;
	}

	/**
	 * 任意类型转换成Map
	 */
	public static Map<String, Object> objectToMap(Object obj) {
		if (obj == null) {
			return null;
		}
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			Field[] declaredFields = obj.getClass().getDeclaredFields();
			for (Field field : declaredFields) {
				field.setAccessible(true);
				if (field.get(obj) != null) {
					map.put(field.getName(), field.get(obj));
				} else {
					map.put(field.getName(), "");
				}
			}
		} catch (Exception e) {
			throw new RuntimeException("任意类型转换成Map异常");
		}

		return map;
	}

	/**
	 * 对象转换为字符串
	 *
	 * @param obj     转换对象
	 * @param charset 字符集
	 */
	public static String convertToString(Object obj, String charset) {
		try {
			ByteArrayOutputStream bo = new ByteArrayOutputStream();
			ObjectOutputStream oo = new ObjectOutputStream(bo);
			oo.writeObject(obj);
			byte[] data = bo.toByteArray(); // 取内存中保存的数据
			String str = new String(data, charset);
			bo.close();
			oo.close();
			return str;
		} catch (IOException e) {
			throw new RuntimeException("任意类型转换成字符串异常");
		}
	}

	/**
	 * 字节转换为对象
	 *
	 * @param bytes 字节数组
	 */
	public static Object convertToByte(byte[] bytes) {
		try {
			ByteArrayInputStream in = new ByteArrayInputStream(bytes);
			ObjectInputStream ois = new ObjectInputStream(in);
			in.close();
			ois.close();
			Object obj = ois.readObject();
			return obj;
		} catch (ClassNotFoundException | IOException e) {
			e.printStackTrace();
			throw new RuntimeException("字节转换为对象异常");
		}
	}

	/**
	 * 从map集合中获取属性值
	 *
	 * @param <E>          返回对象
	 * @param map          map集合
	 * @param key          键对
	 * @param defaultValue 默认值
	 */
	public final static <E> E get(Map<String, Object> map, Object key, E defaultValue) {
		Object o = map.get(key);
		if (o == null)
			return defaultValue;
		return (E) o;
	}

	public static Object[] list2Array(List<?> list) {
		Object[] objs = new Object[list.size()];
		if (list.size() > 0) {
			list.toArray(objs);
		}
		return objs;
	}

	/**
	 * uniCode编码转换中文
	 */
	public static String unicodeToString(String str) {
		Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
		Matcher matcher = pattern.matcher(str);
		char ch;
		while (matcher.find()) {
			// group 6728
			String group = matcher.group(2);
			// ch:'木' 26408
			ch = (char) Integer.parseInt(group, 16);
			// group1 \u6728
			String group1 = matcher.group(1);
			str = str.replace(group1, ch + "");
		}
		return str;
	}

	/**
	 * 删除集合中的指定字符串
	 * @param list
	 * @param delStr
	 */
	public static void listRemove(List<String> list, String delStr) {
		Iterator<String> it = list.iterator();
		while (it.hasNext()) {
			String s = it.next();
			if (delStr.equals(s)) {
				it.remove();
			}
		}
	}

	/**
	 * 将参数转换为集合
	 *
	 * @param isLinked true为链表结构集合，false为动态数组的数据结构集合
	 * @param values   可变参数
	 */
	public static <T> List<T> list(boolean isLinked, T... values) {
		List<T> arrayList = list(isLinked);
		if (OftenUtil.isNotEmpty(values)) {
			Object[] objs = values;
			for (Object o : objs) {
				arrayList.add((T) o);
			}
		}
		return arrayList;
	}

	/**
	 * 根据条件创建集合
	 *
	 * @param isLinked true为链表结构集合，false为动态数组的数据结构集合
	 */
	public static <T> List<T> list(boolean isLinked) {
		return (List) (isLinked ? new LinkedList() : new ArrayList());
	}

	/**
	 * 将参数创建为动态数组结构集合
	 *
	 * @param values 可变参数
	 */
	public static <T> ArrayList<T> newArrayList(T... values) {
		return (ArrayList) list(false, values);
	}
}
